package com.foton.bpc.all.util;

import com.foton.bpc.all.config.ProtocolConfig;
import com.foton.bpc.all.config.RefrenceConfig;
import com.foton.bpc.all.config.RegisterConfig;
import com.foton.bpc.all.config.ServiceConfig;
import com.foton.bpc.all.register.Register;
import com.foton.bpc.all.register.cluster.ClusterInvoker;
import com.foton.bpc.all.remoting.Transport;
import com.foton.bpc.all.remoting.dto.BpcInvacation;
import com.foton.bpc.all.remoting.invoker.Invoker;
import com.foton.bpc.all.remoting.invoker.impl.BpcClientInvoker;
import com.foton.bpc.all.remoting.invoker.proxy.ProxyFactroy;
import com.foton.bpc.all.remoting.rpc.Protocol;
import com.foton.bpc.all.remoting.rpc.impl.BpcProtocol;
import com.foton.bpc.all.serialzation.Serialzation;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;

import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

/**
 * @Author RenPu
 * @Date 2023/6/8 18:15
 * @Version 1.0
 * @Description: 引导类处理器
 *               启动网络服务
 *               服务的暴露等工作
 **/

@Slf4j
public class BootStrapManage {



    /**
     * 服务提供者---暴露服务
     * @param serviceConfig
     */
    public static void exportService(ServiceConfig serviceConfig)  {

        Invoker invoker = ProxyFactroy.getInvoker(serviceConfig.getReference(), serviceConfig.getService());
        try {
            //invoker对象
            //根据协议进行暴露，有多个协议就暴露多次
            for (ProtocolConfig protocolConfig : serviceConfig.getProtocolConfigs()) {
                //根据 协议:ip:端口/service全类名？配置项=值&配置项

                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(protocolConfig.getName()).append("://");
                //获取网卡ip,获取网卡设备的第一个InetAddress的HostAddress
                String hostAddress = NetworkInterface.getNetworkInterfaces().nextElement()
                        .getInterfaceAddresses()
                        .get(0).getAddress()
                        .getHostAddress();
                //端口+service的全类名+协议号+序列化方式
                stringBuilder.append(hostAddress + ":").append(protocolConfig.getPort() + "/").append(serviceConfig.getService().getName() + "?")
                        .append("transport=" + protocolConfig.getTransport()).append("&serialization=" + protocolConfig.getSerialization());
                URI exporeUri = new URI(stringBuilder.toString());

                Protocol protocol = (Protocol)SpIUtils.getServiceImpl(protocolConfig.getName(), Protocol.class);

                protocol.export(exporeUri,invoker);

                //todo 此处可以把暴露的服务注册到中心,通过SPI的机制实现注册中心的具体实现的灵活配置
                for (RegisterConfig registerConfig : serviceConfig.getRegisterConfigs()) {
                    URI registerUri = new URI(registerConfig.getAddress());
                    Register register = (Register)SpIUtils.getServiceImpl(registerUri.getScheme(), Register.class);
                    //初始化配置参数，开启周期续约任务
                    register.init(registerUri);
                    //将暴露得服务添加注册中心维护
                    register.register(exporeUri);
                }
                log.info("准备暴露服务：： ：：：" + exporeUri);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }


    /**
     * 服务调用者---生成代理类对象，注入到被BpcRefrence注解标注的Filed
     * @param refrenceConfig
     * @return
     */
    public static Object getRefrenceBean(RefrenceConfig refrenceConfig){
        Object proxy=null;
        //实现集群注册中心，进行获取暴露得服务实例
        ClusterInvoker clusterInvoker= null;
        try {
            clusterInvoker = new ClusterInvoker(refrenceConfig);
            //使用JDK动态代理的形式，进行生成代理对象
             proxy = ProxyFactroy.getProxy(clusterInvoker, new Class[]{refrenceConfig.getService()});
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return proxy;

    }




}
